home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / generic / tkTextWind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  34.6 KB  |  1,177 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkTextWind.c --
  3.  *
  4.  *    This file contains code that allows arbitrary windows to be
  5.  *    nested inside text widgets.  It also implements the "window"
  6.  *    widget command for texts.
  7.  *
  8.  * Copyright (c) 1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * SCCS: @(#) tkTextWind.c 1.14 97/04/25 16:52:09
  15.  */
  16.  
  17. #include "tk.h"
  18. #include "tkText.h"
  19. #include "tkPort.h"
  20.  
  21. /*
  22.  * The following structure is the official type record for the
  23.  * embedded window geometry manager:
  24.  */
  25.  
  26. static void        EmbWinRequestProc _ANSI_ARGS_((ClientData clientData,
  27.                 Tk_Window tkwin));
  28. static void        EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData,
  29.                 Tk_Window tkwin));
  30.  
  31. static Tk_GeomMgr textGeomType = {
  32.     "text",            /* name */
  33.     EmbWinRequestProc,        /* requestProc */
  34.     EmbWinLostSlaveProc,    /* lostSlaveProc */
  35. };
  36.  
  37. /*
  38.  * Definitions for alignment values:
  39.  */
  40.  
  41. #define ALIGN_BOTTOM        0
  42. #define ALIGN_CENTER        1
  43. #define ALIGN_TOP        2
  44. #define ALIGN_BASELINE        3
  45.  
  46. /*
  47.  * Macro that determines the size of an embedded window segment:
  48.  */
  49.  
  50. #define EW_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \
  51.     + sizeof(TkTextEmbWindow)))
  52.  
  53. /*
  54.  * Prototypes for procedures defined in this file:
  55.  */
  56.  
  57. static int        AlignParseProc _ANSI_ARGS_((ClientData clientData,
  58.                 Tcl_Interp *interp, Tk_Window tkwin, char *value,
  59.                 char *widgRec, int offset));
  60. static char *        AlignPrintProc _ANSI_ARGS_((ClientData clientData,
  61.                 Tk_Window tkwin, char *widgRec, int offset,
  62.                 Tcl_FreeProc **freeProcPtr));
  63. static TkTextSegment *    EmbWinCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,
  64.                 TkTextLine *linePtr));
  65. static void        EmbWinCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
  66.                 TkTextLine *linePtr));
  67. static void        EmbWinBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
  68.                 int index, int y, int lineHeight, int baseline,
  69.                 int *xPtr, int *yPtr, int *widthPtr,
  70.                 int *heightPtr));
  71. static int        EmbWinConfigure _ANSI_ARGS_((TkText *textPtr,
  72.                 TkTextSegment *ewPtr, int argc, char **argv));
  73. static void        EmbWinDelayedUnmap _ANSI_ARGS_((
  74.                 ClientData clientData));
  75. static int        EmbWinDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,
  76.                 TkTextLine *linePtr, int treeGone));
  77. static void        EmbWinDisplayProc _ANSI_ARGS_((
  78.                 TkTextDispChunk *chunkPtr, int x, int y,
  79.                 int lineHeight, int baseline, Display *display,
  80.                 Drawable dst, int screenY));
  81. static int        EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr,
  82.                 TkTextIndex *indexPtr, TkTextSegment *segPtr,
  83.                 int offset, int maxX, int maxChars,
  84.                 int noCharsYet, Tk_Uid wrapMode,
  85.                 TkTextDispChunk *chunkPtr));
  86. static void        EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,
  87.                 XEvent *eventPtr));
  88. static void        EmbWinUndisplayProc _ANSI_ARGS_((TkText *textPtr,
  89.                 TkTextDispChunk *chunkPtr));
  90.  
  91. /*
  92.  * The following structure declares the "embedded window" segment type.
  93.  */
  94.  
  95. static Tk_SegType tkTextEmbWindowType = {
  96.     "window",                    /* name */
  97.     0,                        /* leftGravity */
  98.     (Tk_SegSplitProc *) NULL,            /* splitProc */
  99.     EmbWinDeleteProc,                /* deleteProc */
  100.     EmbWinCleanupProc,                /* cleanupProc */
  101.     (Tk_SegLineChangeProc *) NULL,        /* lineChangeProc */
  102.     EmbWinLayoutProc,                /* layoutProc */
  103.     EmbWinCheckProc                /* checkProc */
  104. };
  105.  
  106. /*
  107.  * Information used for parsing window configuration options:
  108.  */
  109.  
  110. static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,
  111.     (ClientData) NULL};
  112.  
  113. static Tk_ConfigSpec configSpecs[] = {
  114.     {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
  115.     "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
  116.     {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,
  117.     (char *) NULL, Tk_Offset(TkTextEmbWindow, create),
  118.     TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
  119.     {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,
  120.     "0", Tk_Offset(TkTextEmbWindow, padX),
  121.     TK_CONFIG_DONT_SET_DEFAULT},
  122.     {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,
  123.     "0", Tk_Offset(TkTextEmbWindow, padY),
  124.     TK_CONFIG_DONT_SET_DEFAULT},
  125.     {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
  126.     "0", Tk_Offset(TkTextEmbWindow, stretch),
  127.     TK_CONFIG_DONT_SET_DEFAULT},
  128.     {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
  129.     (char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin),
  130.     TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
  131.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  132.     (char *) NULL, 0, 0}
  133. };
  134.  
  135. /*
  136.  *--------------------------------------------------------------
  137.  *
  138.  * TkTextWindowCmd --
  139.  *
  140.  *    This procedure implements the "window" widget command
  141.  *    for text widgets.  See the user documentation for details
  142.  *    on what it does.
  143.  *
  144.  * Results:
  145.  *    A standard Tcl result or error.
  146.  *
  147.  * Side effects:
  148.  *    See the user documentation.
  149.  *
  150.  *--------------------------------------------------------------
  151.  */
  152.  
  153. int
  154. TkTextWindowCmd(textPtr, interp, argc, argv)
  155.     register TkText *textPtr;    /* Information about text widget. */
  156.     Tcl_Interp *interp;        /* Current interpreter. */
  157.     int argc;            /* Number of arguments. */
  158.     char **argv;        /* Argument strings.  Someone else has already
  159.                  * parsed this command enough to know that
  160.                  * argv[1] is "window". */
  161. {
  162.     size_t length;
  163.     register TkTextSegment *ewPtr;
  164.  
  165.     if (argc < 3) {
  166.     Tcl_AppendResult(interp, "wrong # args: should be \"",
  167.         argv[0], " window option ?arg arg ...?\"", (char *) NULL);
  168.     return TCL_ERROR;
  169.     }
  170.     length = strlen(argv[2]);
  171.     if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
  172.     TkTextIndex index;
  173.     TkTextSegment *ewPtr;
  174.  
  175.     if (argc != 5) {
  176.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  177.             argv[0], " window cget index option\"",
  178.             (char *) NULL);
  179.         return TCL_ERROR;
  180.     }
  181.     if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
  182.         return TCL_ERROR;
  183.     }
  184.     ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
  185.     if (ewPtr->typePtr != &tkTextEmbWindowType) {
  186.         Tcl_AppendResult(interp, "no embedded window at index \"",
  187.             argv[3], "\"", (char *) NULL);
  188.         return TCL_ERROR;
  189.     }
  190.     return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
  191.         (char *) &ewPtr->body.ew, argv[4], 0);
  192.     } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
  193.     TkTextIndex index;
  194.     TkTextSegment *ewPtr;
  195.  
  196.     if (argc < 4) {
  197.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  198.             argv[0], " window configure index ?option value ...?\"",
  199.             (char *) NULL);
  200.         return TCL_ERROR;
  201.     }
  202.     if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
  203.         return TCL_ERROR;
  204.     }
  205.     ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
  206.     if (ewPtr->typePtr != &tkTextEmbWindowType) {
  207.         Tcl_AppendResult(interp, "no embedded window at index \"",
  208.             argv[3], "\"", (char *) NULL);
  209.         return TCL_ERROR;
  210.     }
  211.     if (argc == 4) {
  212.         return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
  213.             (char *) &ewPtr->body.ew, (char *) NULL, 0);
  214.     } else if (argc == 5) {
  215.         return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
  216.             (char *) &ewPtr->body.ew, argv[4], 0);
  217.     } else {
  218.         TkTextChanged(textPtr, &index, &index);
  219.         return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4);
  220.     }
  221.     } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
  222.     TkTextIndex index;
  223.     int lineIndex;
  224.  
  225.     /*
  226.      * Add a new window.  Find where to put the new window, and
  227.      * mark that position for redisplay.
  228.      */
  229.  
  230.     if (argc < 4) {
  231.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  232.             argv[0], " window create index ?option value ...?\"",
  233.             (char *) NULL);
  234.         return TCL_ERROR;
  235.     }
  236.     if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
  237.         return TCL_ERROR;
  238.     }
  239.  
  240.     /*
  241.      * Don't allow insertions on the last (dummy) line of the text.
  242.      */
  243.     
  244.     lineIndex = TkBTreeLineIndex(index.linePtr);
  245.     if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
  246.         lineIndex--;
  247.         TkTextMakeIndex(textPtr->tree, lineIndex, 1000000, &index);
  248.     }
  249.  
  250.     /*
  251.      * Create the new window segment and initialize it.
  252.      */
  253.  
  254.     ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);
  255.     ewPtr->typePtr = &tkTextEmbWindowType;
  256.     ewPtr->size = 1;
  257.     ewPtr->body.ew.textPtr = textPtr;
  258.     ewPtr->body.ew.linePtr = NULL;
  259.     ewPtr->body.ew.tkwin = NULL;
  260.     ewPtr->body.ew.create = NULL;
  261.     ewPtr->body.ew.align = ALIGN_CENTER;
  262.     ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
  263.     ewPtr->body.ew.stretch = 0;
  264.     ewPtr->body.ew.chunkCount = 0;
  265.     ewPtr->body.ew.displayed = 0;
  266.  
  267.     /*
  268.      * Link the segment into the text widget, then configure it (delete
  269.      * it again if the configuration fails).
  270.      */
  271.  
  272.     TkTextChanged(textPtr, &index, &index);
  273.     TkBTreeLinkSegment(ewPtr, &index);
  274.     if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) {
  275.         TkTextIndex index2;
  276.  
  277.         TkTextIndexForwChars(&index, 1, &index2);
  278.         TkBTreeDeleteChars(&index, &index2);
  279.         return TCL_ERROR;
  280.     }
  281.     } else if (strncmp(argv[2], "names", length) == 0) {
  282.     Tcl_HashSearch search;
  283.     Tcl_HashEntry *hPtr;
  284.  
  285.     if (argc != 3) {
  286.         Tcl_AppendResult(interp, "wrong # args: should be \"",
  287.             argv[0], " window names\"", (char *) NULL);
  288.         return TCL_ERROR;
  289.     }
  290.     for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);
  291.         hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  292.         Tcl_AppendElement(interp,
  293.             Tcl_GetHashKey(&textPtr->markTable, hPtr));
  294.     }
  295.     } else {
  296.     Tcl_AppendResult(interp, "bad window option \"", argv[2],
  297.         "\": must be cget, configure, create, or names",
  298.         (char *) NULL);
  299.     return TCL_ERROR;
  300.     }
  301.     return TCL_OK;
  302. }
  303.  
  304. /*
  305.  *--------------------------------------------------------------
  306.  *
  307.  * EmbWinConfigure --
  308.  *
  309.  *    This procedure is called to handle configuration options
  310.  *    for an embedded window, using an argc/argv list.
  311.  *
  312.  * Results:
  313.  *    The return value is a standard Tcl result.  If TCL_ERROR is
  314.  *    returned, then interp->result contains an error message..
  315.  *
  316.  * Side effects:
  317.  *    Configuration information for the embedded window changes,
  318.  *    such as alignment, stretching, or name of the embedded
  319.  *    window.
  320.  *
  321.  *--------------------------------------------------------------
  322.  */
  323.  
  324. static int
  325. EmbWinConfigure(textPtr, ewPtr, argc, argv)
  326.     TkText *textPtr;        /* Information about text widget that
  327.                  * contains embedded window. */
  328.     TkTextSegment *ewPtr;    /* Embedded window to be configured. */
  329.     int argc;            /* Number of strings in argv. */
  330.     char **argv;        /* Array of strings describing configuration
  331.                  * options. */
  332. {
  333.     Tk_Window oldWindow;
  334.     Tcl_HashEntry *hPtr;
  335.     int new;
  336.  
  337.     oldWindow = ewPtr->body.ew.tkwin;
  338.     if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,
  339.         argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)
  340.         != TCL_OK) {
  341.     return TCL_ERROR;
  342.     }
  343.     if (oldWindow != ewPtr->body.ew.tkwin) {
  344.     if (oldWindow != NULL) {
  345.         Tcl_DeleteHashEntry(Tcl_FindHashEntry(&textPtr->windowTable,
  346.             Tk_PathName(oldWindow)));
  347.         Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
  348.             EmbWinStructureProc, (ClientData) ewPtr);
  349.         Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
  350.             (ClientData) NULL);
  351.         if (textPtr->tkwin != Tk_Parent(oldWindow)) {
  352.         Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);
  353.         } else {
  354.         Tk_UnmapWindow(oldWindow);
  355.         }
  356.     }
  357.     if (ewPtr->body.ew.tkwin != NULL) {
  358.         Tk_Window ancestor, parent;
  359.  
  360.         /*
  361.          * Make sure that the text is either the parent of the
  362.          * embedded window or a descendant of that parent.  Also,
  363.          * don't allow a top-level window to be managed inside
  364.          * a text.
  365.          */
  366.  
  367.         parent = Tk_Parent(ewPtr->body.ew.tkwin);
  368.         for (ancestor = textPtr->tkwin; ;
  369.             ancestor = Tk_Parent(ancestor)) {
  370.         if (ancestor == parent) {
  371.             break;
  372.         }
  373.         if (Tk_IsTopLevel(ancestor)) {
  374.             badMaster:
  375.             Tcl_AppendResult(textPtr->interp, "can't embed ",
  376.                 Tk_PathName(ewPtr->body.ew.tkwin), " in ",
  377.                 Tk_PathName(textPtr->tkwin), (char *) NULL);
  378.             ewPtr->body.ew.tkwin = NULL;
  379.             return TCL_ERROR;
  380.         }
  381.         }
  382.         if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
  383.             || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {
  384.         goto badMaster;
  385.         }
  386.  
  387.         /*
  388.          * Take over geometry management for the window, plus create
  389.          * an event handler to find out when it is deleted.
  390.          */
  391.  
  392.         Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
  393.             (ClientData) ewPtr);
  394.         Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
  395.             EmbWinStructureProc, (ClientData) ewPtr);
  396.  
  397.         /*
  398.          * Special trick!  Must enter into the hash table *after*
  399.          * calling Tk_ManageGeometry:  if the window was already managed
  400.          * elsewhere in this text, the Tk_ManageGeometry call will cause
  401.          * the entry to be removed, which could potentially lose the new
  402.          * entry.
  403.          */
  404.  
  405.         hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
  406.             Tk_PathName(ewPtr->body.ew.tkwin), &new);
  407.         Tcl_SetHashValue(hPtr, ewPtr);
  408.  
  409.     }
  410.     }
  411.     return TCL_OK;
  412. }
  413.  
  414. /*
  415.  *--------------------------------------------------------------
  416.  *
  417.  * AlignParseProc --
  418.  *
  419.  *    This procedure is invoked by Tk_ConfigureWidget during
  420.  *    option processing to handle "-align" options for embedded
  421.  *    windows.
  422.  *
  423.  * Results:
  424.  *    A standard Tcl return value.
  425.  *
  426.  * Side effects:
  427.  *    The alignment for the embedded window may change.
  428.  *
  429.  *--------------------------------------------------------------
  430.  */
  431.  
  432.     /* ARGSUSED */
  433. static int
  434. AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)
  435.     ClientData clientData;        /* Not used.*/
  436.     Tcl_Interp *interp;            /* Used for reporting errors. */
  437.     Tk_Window tkwin;            /* Window for text widget. */
  438.     char *value;            /* Value of option. */
  439.     char *widgRec;            /* Pointer to TkTextEmbWindow
  440.                      * structure. */
  441.     int offset;                /* Offset into item (ignored). */
  442. {
  443.     register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec;
  444.  
  445.     if (strcmp(value, "baseline") == 0) {
  446.     embPtr->align = ALIGN_BASELINE;
  447.     } else if (strcmp(value, "bottom") == 0) {
  448.     embPtr->align = ALIGN_BOTTOM;
  449.     } else if (strcmp(value, "center") == 0) {
  450.     embPtr->align = ALIGN_CENTER;
  451.     } else if (strcmp(value, "top") == 0) {
  452.     embPtr->align = ALIGN_TOP;
  453.     } else {
  454.     Tcl_AppendResult(interp, "bad alignment \"", value,
  455.         "\": must be baseline, bottom, center, or top",
  456.         (char *) NULL);
  457.     return TCL_ERROR;
  458.     }
  459.     return TCL_OK;
  460. }
  461.  
  462. /*
  463.  *--------------------------------------------------------------
  464.  *
  465.  * AlignPrintProc --
  466.  *
  467.  *    This procedure is invoked by the Tk configuration code
  468.  *    to produce a printable string for the "-align" configuration
  469.  *    option for embedded windows.
  470.  *
  471.  * Results:
  472.  *    The return value is a string describing the embedded
  473.  *    window's current alignment.
  474.  *
  475.  * Side effects:
  476.  *    None.
  477.  *
  478.  *--------------------------------------------------------------
  479.  */
  480.  
  481.     /* ARGSUSED */
  482. static char *
  483. AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
  484.     ClientData clientData;        /* Ignored. */
  485.     Tk_Window tkwin;            /* Window for text widget. */
  486.     char *widgRec;            /* Pointer to TkTextEmbWindow
  487.                      * structure. */
  488.     int offset;                /* Ignored. */
  489.     Tcl_FreeProc **freeProcPtr;        /* Pointer to variable to fill in with
  490.                      * information about how to reclaim
  491.                      * storage for return string. */
  492. {
  493.     switch (((TkTextEmbWindow *) widgRec)->align) {
  494.     case ALIGN_BASELINE:
  495.         return "baseline";
  496.     case ALIGN_BOTTOM:
  497.         return "bottom";
  498.     case ALIGN_CENTER:
  499.         return "center";
  500.     case ALIGN_TOP:
  501.         return "top";
  502.     default:
  503.         return "??";
  504.     }
  505. }
  506.  
  507. /*
  508.  *--------------------------------------------------------------
  509.  *
  510.  * EmbWinStructureProc --
  511.  *
  512.  *    This procedure is invoked by the Tk event loop whenever
  513.  *    StructureNotify events occur for a window that's embedded
  514.  *    in a text widget.  This procedure's only purpose is to
  515.  *    clean up when windows are deleted.
  516.  *
  517.  * Results:
  518.  *    None.
  519.  *
  520.  * Side effects:
  521.  *    The window is disassociated from the window segment, and
  522.  *    the portion of the text is redisplayed.
  523.  *
  524.  *--------------------------------------------------------------
  525.  */
  526.  
  527. static void
  528. EmbWinStructureProc(clientData, eventPtr)
  529.     ClientData clientData;    /* Pointer to record describing window item. */
  530.     XEvent *eventPtr;        /* Describes what just happened. */
  531. {
  532.     register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
  533.     TkTextIndex index;
  534.  
  535.     if (eventPtr->type != DestroyNotify) {
  536.     return;
  537.     }
  538.  
  539.     Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
  540.         Tk_PathName(ewPtr->body.ew.tkwin)));
  541.     ewPtr->body.ew.tkwin = NULL;
  542.     index.tree = ewPtr->body.ew.textPtr->tree;
  543.     index.linePtr = ewPtr->body.ew.linePtr;
  544.     index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
  545.     TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
  546. }
  547.  
  548. /*
  549.  *--------------------------------------------------------------
  550.  *
  551.  * EmbWinRequestProc --
  552.  *
  553.  *    This procedure is invoked whenever a window that's associated
  554.  *    with a window canvas item changes its requested dimensions.
  555.  *
  556.  * Results:
  557.  *    None.
  558.  *
  559.  * Side effects:
  560.  *    The size and location on the screen of the window may change,
  561.  *    depending on the options specified for the window item.
  562.  *
  563.  *--------------------------------------------------------------
  564.  */
  565.  
  566.     /* ARGSUSED */
  567. static void
  568. EmbWinRequestProc(clientData, tkwin)
  569.     ClientData clientData;        /* Pointer to record for window item. */
  570.     Tk_Window tkwin;            /* Window that changed its desired
  571.                      * size. */
  572. {
  573.     TkTextSegment *ewPtr = (TkTextSegment *) clientData;
  574.     TkTextIndex index;
  575.  
  576.     index.tree = ewPtr->body.ew.textPtr->tree;
  577.     index.linePtr = ewPtr->body.ew.linePtr;
  578.     index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
  579.     TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
  580. }
  581.  
  582. /*
  583.  *--------------------------------------------------------------
  584.  *
  585.  * EmbWinLostSlaveProc --
  586.  *
  587.  *    This procedure is invoked by the Tk geometry manager when
  588.  *    a slave window managed by a text widget is claimed away
  589.  *    by another geometry manager.
  590.  *
  591.  * Results:
  592.  *    None.
  593.  *
  594.  * Side effects:
  595.  *    The window is disassociated from the window segment, and
  596.  *    the portion of the text is redisplayed.
  597.  *
  598.  *--------------------------------------------------------------
  599.  */
  600.  
  601. static void
  602. EmbWinLostSlaveProc(clientData, tkwin)
  603.     ClientData clientData;    /* Pointer to record describing window item. */
  604.     Tk_Window tkwin;        /* Window that was claimed away by another
  605.                  * geometry manager. */
  606. {
  607.     register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
  608.     TkTextIndex index;
  609.  
  610.     Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
  611.         EmbWinStructureProc, (ClientData) ewPtr);
  612.     Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
  613.     if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
  614.     Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
  615.     } else {
  616.     Tk_UnmapWindow(tkwin);
  617.     }
  618.     Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
  619.         Tk_PathName(ewPtr->body.ew.tkwin)));
  620.     ewPtr->body.ew.tkwin = NULL;
  621.     index.tree = ewPtr->body.ew.textPtr->tree;
  622.     index.linePtr = ewPtr->body.ew.linePtr;
  623.     index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
  624.     TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
  625. }
  626.  
  627. /*
  628.  *--------------------------------------------------------------
  629.  *
  630.  * EmbWinDeleteProc --
  631.  *
  632.  *    This procedure is invoked by the text B-tree code whenever
  633.  *    an embedded window lies in a range of characters being deleted.
  634.  *
  635.  * Results:
  636.  *    Returns 0 to indicate that the deletion has been accepted.
  637.  *
  638.  * Side effects:
  639.  *    The embedded window is deleted, if it exists, and any resources
  640.  *    associated with it are released.
  641.  *
  642.  *--------------------------------------------------------------
  643.  */
  644.  
  645.     /* ARGSUSED */
  646. static int
  647. EmbWinDeleteProc(ewPtr, linePtr, treeGone)
  648.     TkTextSegment *ewPtr;        /* Segment being deleted. */
  649.     TkTextLine *linePtr;        /* Line containing segment. */
  650.     int treeGone;            /* Non-zero means the entire tree is
  651.                      * being deleted, so everything must
  652.                      * get cleaned up. */
  653. {
  654.     Tcl_HashEntry *hPtr;
  655.  
  656.     if (ewPtr->body.ew.tkwin != NULL) {
  657.     hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
  658.         Tk_PathName(ewPtr->body.ew.tkwin));
  659.     if (hPtr != NULL) {
  660.         /*
  661.          * (It's possible for there to be no hash table entry for this
  662.          * window, if an error occurred while creating the window segment
  663.          * but before the window got added to the table)
  664.          */
  665.  
  666.         Tcl_DeleteHashEntry(hPtr);
  667.     }
  668.  
  669.     /*
  670.      * Delete the event handler for the window before destroying
  671.      * the window, so that EmbWinStructureProc doesn't get called
  672.      * (we'll already do everything that it would have done, and
  673.      * it will just get confused).
  674.      */
  675.  
  676.     Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
  677.         EmbWinStructureProc, (ClientData) ewPtr);
  678.     Tk_DestroyWindow(ewPtr->body.ew.tkwin);
  679.     }
  680.     Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
  681.     Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,
  682.         ewPtr->body.ew.textPtr->display, 0);
  683.     ckfree((char *) ewPtr);
  684.     return 0;
  685. }
  686.  
  687. /*
  688.  *--------------------------------------------------------------
  689.  *
  690.  * EmbWinCleanupProc --
  691.  *
  692.  *    This procedure is invoked by the B-tree code whenever a
  693.  *    segment containing an embedded window is moved from one
  694.  *    line to another.
  695.  *
  696.  * Results:
  697.  *    None.
  698.  *
  699.  * Side effects:
  700.  *    The linePtr field of the segment gets updated.
  701.  *
  702.  *--------------------------------------------------------------
  703.  */
  704.  
  705. static TkTextSegment *
  706. EmbWinCleanupProc(ewPtr, linePtr)
  707.     TkTextSegment *ewPtr;        /* Mark segment that's being moved. */
  708.     TkTextLine *linePtr;        /* Line that now contains segment. */
  709. {
  710.     ewPtr->body.ew.linePtr = linePtr;
  711.     return ewPtr;
  712. }
  713.  
  714. /*
  715.  *--------------------------------------------------------------
  716.  *
  717.  * EmbWinLayoutProc --
  718.  *
  719.  *    This procedure is the "layoutProc" for embedded window
  720.  *    segments.
  721.  *
  722.  * Results:
  723.  *    1 is returned to indicate that the segment should be
  724.  *    displayed.  The chunkPtr structure is filled in.
  725.  *
  726.  * Side effects:
  727.  *    None, except for filling in chunkPtr.
  728.  *
  729.  *--------------------------------------------------------------
  730.  */
  731.  
  732.     /*ARGSUSED*/
  733. static int
  734. EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
  735.     noCharsYet, wrapMode, chunkPtr)
  736.     TkText *textPtr;        /* Text widget being layed out. */
  737.     TkTextIndex *indexPtr;    /* Identifies first character in chunk. */
  738.     TkTextSegment *ewPtr;    /* Segment corresponding to indexPtr. */
  739.     int offset;            /* Offset within segPtr corresponding to
  740.                  * indexPtr (always 0). */
  741.     int maxX;            /* Chunk must not occupy pixels at this
  742.                  * position or higher. */
  743.     int maxChars;        /* Chunk must not include more than this
  744.                  * many characters. */
  745.     int noCharsYet;        /* Non-zero means no characters have been
  746.                  * assigned to this line yet. */
  747.     Tk_Uid wrapMode;        /* Wrap mode to use for line: tkTextCharUid,
  748.                  * tkTextNoneUid, or tkTextWordUid. */
  749.     register TkTextDispChunk *chunkPtr;
  750.                 /* Structure to fill in with information
  751.                  * about this chunk.  The x field has already
  752.                  * been set by the caller. */
  753. {
  754.     int width, height;
  755.  
  756.     if (offset != 0) {
  757.     panic("Non-zero offset in EmbWinLayoutProc");
  758.     }
  759.  
  760.     if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
  761.     int code, new;
  762.     Tcl_DString name;
  763.     Tk_Window ancestor;
  764.     Tcl_HashEntry *hPtr;
  765.  
  766.     /*
  767.      * The window doesn't currently exist.  Create it by evaluating
  768.      * the creation script.  The script must return the window's
  769.      * path name:  look up that name to get back to the window
  770.      * token.  Then register ourselves as the geometry manager for
  771.      * the window.
  772.      */
  773.  
  774.     code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);
  775.     if (code != TCL_OK) {
  776.         createError:
  777.         Tcl_BackgroundError(textPtr->interp);
  778.         goto gotWindow;
  779.     }
  780.     Tcl_DStringInit(&name);
  781.     Tcl_DStringAppend(&name, textPtr->interp->result, -1);
  782.     Tcl_ResetResult(textPtr->interp);
  783.     ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
  784.         Tcl_DStringValue(&name), textPtr->tkwin);
  785.     if (ewPtr->body.ew.tkwin == NULL) {
  786.         goto createError;
  787.     }
  788.     for (ancestor = textPtr->tkwin; ;
  789.         ancestor = Tk_Parent(ancestor)) {
  790.         if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
  791.         break;
  792.         }
  793.         if (Tk_IsTopLevel(ancestor)) {
  794.         badMaster:
  795.         Tcl_AppendResult(textPtr->interp, "can't embed ",
  796.             Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",
  797.             Tk_PathName(textPtr->tkwin), (char *) NULL);
  798.         Tcl_BackgroundError(textPtr->interp);
  799.         ewPtr->body.ew.tkwin = NULL;
  800.         goto gotWindow;
  801.         }
  802.     }
  803.     if (Tk_IsTopLevel(ewPtr->body.ew.tkwin)
  804.         || (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
  805.         goto badMaster;
  806.     }
  807.     Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
  808.         (ClientData) ewPtr);
  809.     Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
  810.         EmbWinStructureProc, (ClientData) ewPtr);
  811.  
  812.     /*
  813.      * Special trick!  Must enter into the hash table *after*
  814.      * calling Tk_ManageGeometry:  if the window was already managed
  815.      * elsewhere in this text, the Tk_ManageGeometry call will cause
  816.      * the entry to be removed, which could potentially lose the new
  817.      * entry.
  818.      */
  819.  
  820.     hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
  821.         Tk_PathName(ewPtr->body.ew.tkwin), &new);
  822.     Tcl_SetHashValue(hPtr, ewPtr);
  823.     }
  824.  
  825.     /*
  826.      * See if there's room for this window on this line.
  827.      */
  828.  
  829.     gotWindow:
  830.     if (ewPtr->body.ew.tkwin == NULL) {
  831.     width = 0;
  832.     height = 0;
  833.     } else {
  834.     width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;
  835.     height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
  836.     }
  837.     if ((width > (maxX - chunkPtr->x))
  838.         && !noCharsYet && (textPtr->wrapMode != tkTextNoneUid)) {
  839.     return 0;
  840.     }
  841.  
  842.     /*
  843.      * Fill in the chunk structure.
  844.      */
  845.  
  846.     chunkPtr->displayProc = EmbWinDisplayProc;
  847.     chunkPtr->undisplayProc = EmbWinUndisplayProc;
  848.     chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
  849.     chunkPtr->bboxProc = EmbWinBboxProc;
  850.     chunkPtr->numChars = 1;
  851.     if (ewPtr->body.ew.align == ALIGN_BASELINE) {
  852.     chunkPtr->minAscent = height - ewPtr->body.ew.padY;
  853.     chunkPtr->minDescent = ewPtr->body.ew.padY;
  854.     chunkPtr->minHeight = 0;
  855.     } else {
  856.     chunkPtr->minAscent = 0;
  857.     chunkPtr->minDescent = 0;
  858.     chunkPtr->minHeight = height;
  859.     }
  860.     chunkPtr->width = width;
  861.     chunkPtr->breakIndex = -1;
  862.     chunkPtr->breakIndex = 1;
  863.     chunkPtr->clientData = (ClientData) ewPtr;
  864.     ewPtr->body.ew.chunkCount += 1;
  865.     return 1;
  866. }
  867.  
  868. /*
  869.  *--------------------------------------------------------------
  870.  *
  871.  * EmbWinCheckProc --
  872.  *
  873.  *    This procedure is invoked by the B-tree code to perform
  874.  *    consistency checks on embedded windows.
  875.  *
  876.  * Results:
  877.  *    None.
  878.  *
  879.  * Side effects:
  880.  *    The procedure panics if it detects anything wrong with
  881.  *    the embedded window.
  882.  *
  883.  *--------------------------------------------------------------
  884.  */
  885.  
  886. static void
  887. EmbWinCheckProc(ewPtr, linePtr)
  888.     TkTextSegment *ewPtr;        /* Segment to check. */
  889.     TkTextLine *linePtr;        /* Line containing segment. */
  890. {
  891.     if (ewPtr->nextPtr == NULL) {
  892.     panic("EmbWinCheckProc: embedded window is last segment in line");
  893.     }
  894.     if (ewPtr->size != 1) {
  895.     panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
  896.     }
  897. }
  898.  
  899. /*
  900.  *--------------------------------------------------------------
  901.  *
  902.  * EmbWinDisplayProc --
  903.  *
  904.  *    This procedure is invoked by the text displaying code
  905.  *    when it is time to actually draw an embedded window
  906.  *    chunk on the screen.
  907.  *
  908.  * Results:
  909.  *    None.
  910.  *
  911.  * Side effects:
  912.  *    The embedded window gets moved to the correct location
  913.  *    and mapped onto the screen.
  914.  *
  915.  *--------------------------------------------------------------
  916.  */
  917.  
  918. static void
  919. EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
  920.     TkTextDispChunk *chunkPtr;        /* Chunk that is to be drawn. */
  921.     int x;                /* X-position in dst at which to
  922.                      * draw this chunk (differs from
  923.                      * the x-position in the chunk because
  924.                      * of scrolling). */
  925.     int y;                /* Top of rectangular bounding box
  926.                      * for line: tells where to draw this
  927.                      * chunk in dst (x-position is in
  928.                      * the chunk itself). */
  929.     int lineHeight;            /* Total height of line. */
  930.     int baseline;            /* Offset of baseline from y. */
  931.     Display *display;            /* Display to use for drawing. */
  932.     Drawable dst;            /* Pixmap or window in which to draw */
  933.     int screenY;            /* Y-coordinate in text window that
  934.                      * corresponds to y. */
  935. {
  936.     TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
  937.     int lineX, windowX, windowY, width, height;
  938.     Tk_Window tkwin;
  939.  
  940.     tkwin = ewPtr->body.ew.tkwin;
  941.     if (tkwin == NULL) {
  942.     return;
  943.     }
  944.     if ((x + chunkPtr->width) <= 0) {
  945.     /*
  946.      * The window is off-screen;  just unmap it.
  947.      */
  948.  
  949.     if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
  950.         Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
  951.     } else {
  952.         Tk_UnmapWindow(tkwin);
  953.     }
  954.     return;
  955.     }
  956.  
  957.     /*
  958.      * Compute the window's location and size in the text widget, taking
  959.      * into account the align and stretch values for the window.
  960.      */
  961.  
  962.     EmbWinBboxProc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX,
  963.         &windowY, &width, &height);
  964.     windowX = lineX - chunkPtr->x + x;
  965.  
  966.     if (ewPtr->body.ew.textPtr->tkwin == Tk_Parent(tkwin)) {
  967.     if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
  968.         || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
  969.         || (height != Tk_Height(tkwin))) {
  970.         Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
  971.     }
  972.     Tk_MapWindow(tkwin);
  973.     } else {
  974.     Tk_MaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin,
  975.         windowX, windowY, width, height);
  976.     }
  977.  
  978.     /*
  979.      * Mark the window as displayed so that it won't get unmapped.
  980.      */
  981.  
  982.     ewPtr->body.ew.displayed = 1;
  983. }
  984.  
  985. /*
  986.  *--------------------------------------------------------------
  987.  *
  988.  * EmbWinUndisplayProc --
  989.  *
  990.  *    This procedure is called when the chunk for an embedded
  991.  *    window is no longer going to be displayed.  It arranges
  992.  *    for the window associated with the chunk to be unmapped.
  993.  *
  994.  * Results:
  995.  *    None.
  996.  *
  997.  * Side effects:
  998.  *    The window is scheduled for unmapping.
  999.  *
  1000.  *--------------------------------------------------------------
  1001.  */
  1002.  
  1003. static void
  1004. EmbWinUndisplayProc(textPtr, chunkPtr)
  1005.     TkText *textPtr;            /* Overall information about text
  1006.                      * widget. */
  1007.     TkTextDispChunk *chunkPtr;        /* Chunk that is about to be freed. */
  1008. {
  1009.     TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
  1010.  
  1011.     ewPtr->body.ew.chunkCount--;
  1012.     if (ewPtr->body.ew.chunkCount == 0) {
  1013.     /*
  1014.      * Don't unmap the window immediately, since there's a good chance
  1015.      * that it will immediately be redisplayed, perhaps even in the
  1016.      * same place.  Instead, schedule the window to be unmapped later;
  1017.      * the call to EmbWinDelayedUnmap will be cancelled in the likely
  1018.      * event that the unmap becomes unnecessary.
  1019.      */
  1020.  
  1021.     ewPtr->body.ew.displayed = 0;
  1022.     Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) ewPtr);
  1023.     }
  1024. }
  1025.  
  1026. /*
  1027.  *--------------------------------------------------------------
  1028.  *
  1029.  * EmbWinBboxProc --
  1030.  *
  1031.  *    This procedure is called to compute the bounding box of
  1032.  *    the area occupied by an embedded window.
  1033.  *
  1034.  * Results:
  1035.  *    There is no return value.  *xPtr and *yPtr are filled in
  1036.  *    with the coordinates of the upper left corner of the
  1037.  *    window, and *widthPtr and *heightPtr are filled in with
  1038.  *    the dimensions of the window in pixels.  Note:  not all
  1039.  *    of the returned bbox is necessarily visible on the screen
  1040.  *    (the rightmost part might be off-screen to the right,
  1041.  *    and the bottommost part might be off-screen to the bottom).
  1042.  *
  1043.  * Side effects:
  1044.  *    None.
  1045.  *
  1046.  *--------------------------------------------------------------
  1047.  */
  1048.  
  1049. static void
  1050. EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
  1051.     widthPtr, heightPtr)
  1052.     TkTextDispChunk *chunkPtr;        /* Chunk containing desired char. */
  1053.     int index;                /* Index of desired character within
  1054.                      * the chunk. */
  1055.     int y;                /* Topmost pixel in area allocated
  1056.                      * for this line. */
  1057.     int lineHeight;            /* Total height of line. */
  1058.     int baseline;            /* Location of line's baseline, in
  1059.                      * pixels measured down from y. */
  1060.     int *xPtr, *yPtr;            /* Gets filled in with coords of
  1061.                      * character's upper-left pixel. */
  1062.     int *widthPtr;            /* Gets filled in with width of
  1063.                      * character, in pixels. */
  1064.     int *heightPtr;            /* Gets filled in with height of
  1065.                      * character, in pixels. */
  1066. {
  1067.     TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
  1068.     Tk_Window tkwin;
  1069.  
  1070.     tkwin = ewPtr->body.ew.tkwin;
  1071.     if (tkwin != NULL) {
  1072.     *widthPtr = Tk_ReqWidth(tkwin);
  1073.     *heightPtr = Tk_ReqHeight(tkwin);
  1074.     } else {
  1075.     *widthPtr = 0;
  1076.     *heightPtr = 0;
  1077.     }
  1078.     *xPtr = chunkPtr->x + ewPtr->body.ew.padX;
  1079.     if (ewPtr->body.ew.stretch) {
  1080.     if (ewPtr->body.ew.align == ALIGN_BASELINE) {
  1081.         *heightPtr = baseline - ewPtr->body.ew.padY;
  1082.     } else {
  1083.         *heightPtr = lineHeight - 2*ewPtr->body.ew.padY;
  1084.     }
  1085.     }
  1086.     switch (ewPtr->body.ew.align) {
  1087.     case ALIGN_BOTTOM:
  1088.         *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
  1089.         break;
  1090.     case ALIGN_CENTER:
  1091.         *yPtr = y + (lineHeight - *heightPtr)/2;
  1092.         break;
  1093.     case ALIGN_TOP:
  1094.         *yPtr = y + ewPtr->body.ew.padY;
  1095.         break;
  1096.     case ALIGN_BASELINE:
  1097.         *yPtr = y + (baseline - *heightPtr);
  1098.         break;
  1099.     }
  1100. }
  1101.  
  1102. /*
  1103.  *--------------------------------------------------------------
  1104.  *
  1105.  * EmbWinDelayedUnmap --
  1106.  *
  1107.  *    This procedure is an idle handler that does the actual
  1108.  *    work of unmapping an embedded window.  See the comment
  1109.  *    in EmbWinUndisplayProc for details.
  1110.  *
  1111.  * Results:
  1112.  *    None.
  1113.  *
  1114.  * Side effects:
  1115.  *    The window gets unmapped, unless its chunk reference count
  1116.  *    has become non-zero again.
  1117.  *
  1118.  *--------------------------------------------------------------
  1119.  */
  1120.  
  1121. static void
  1122. EmbWinDelayedUnmap(clientData)
  1123.     ClientData clientData;        /* Token for the window to
  1124.                      * be unmapped. */
  1125. {
  1126.     TkTextSegment *ewPtr = (TkTextSegment *) clientData;
  1127.  
  1128.     if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) {
  1129.     if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) {
  1130.         Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin,
  1131.             ewPtr->body.ew.textPtr->tkwin);
  1132.     } else {
  1133.         Tk_UnmapWindow(ewPtr->body.ew.tkwin);
  1134.     }
  1135.     }
  1136. }
  1137.  
  1138. /*
  1139.  *--------------------------------------------------------------
  1140.  *
  1141.  * TkTextWindowIndex --
  1142.  *
  1143.  *    Given the name of an embedded window within a text widget,
  1144.  *    returns an index corresponding to the window's position
  1145.  *    in the text.
  1146.  *
  1147.  * Results:
  1148.  *    The return value is 1 if there is an embedded window by
  1149.  *    the given name in the text widget, 0 otherwise.  If the
  1150.  *    window exists, *indexPtr is filled in with its index.
  1151.  *
  1152.  * Side effects:
  1153.  *    None.
  1154.  *
  1155.  *--------------------------------------------------------------
  1156.  */
  1157.  
  1158. int
  1159. TkTextWindowIndex(textPtr, name, indexPtr)
  1160.     TkText *textPtr;        /* Text widget containing window. */
  1161.     char *name;            /* Name of window. */
  1162.     TkTextIndex *indexPtr;    /* Index information gets stored here. */
  1163. {
  1164.     Tcl_HashEntry *hPtr;
  1165.     TkTextSegment *ewPtr;
  1166.  
  1167.     hPtr = Tcl_FindHashEntry(&textPtr->windowTable, name);
  1168.     if (hPtr == NULL) {
  1169.     return 0;
  1170.     }
  1171.     ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
  1172.     indexPtr->tree = textPtr->tree;
  1173.     indexPtr->linePtr = ewPtr->body.ew.linePtr;
  1174.     indexPtr->charIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
  1175.     return 1;
  1176. }
  1177.